package chen.web.back.client.system;

import java.util.ArrayList;
import java.util.List;

import chen.web.back.client.UrlHelper;

import com.extjs.gxt.charts.client.Chart;
import com.extjs.gxt.charts.client.event.ChartEvent;
import com.extjs.gxt.charts.client.event.ChartListener;
import com.extjs.gxt.charts.client.model.ChartModel;
import com.extjs.gxt.charts.client.model.Legend;
import com.extjs.gxt.charts.client.model.LineDataProvider;
import com.extjs.gxt.charts.client.model.Legend.Position;
import com.extjs.gxt.charts.client.model.axis.XAxis;
import com.extjs.gxt.charts.client.model.axis.YAxis;
import com.extjs.gxt.charts.client.model.charts.AreaChart;
import com.extjs.gxt.charts.client.model.charts.LineChart;
import com.extjs.gxt.charts.client.model.charts.PieChart;
import com.extjs.gxt.ui.client.data.BaseModelData;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Info;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.layout.MarginData;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;

public class SystemInfo extends LayoutContainer {

	private ChartListener listener = new ChartListener() {

		public void chartClick(ChartEvent ce) {
			Info.display("Chart Clicked", "You selected {0}.", ""
					+ ce.getValue());
		}
	};

	private Timer updater;  
	@Override
	protected void onRender(Element parent, int index) {
		super.onRender(parent, index);
		ContentPanel cp = new ContentPanel();
		cp.setHeading("CPU使用率");
		cp.setFrame(true);
		cp.setSize(600, 300);
		cp.setLayout(new FitLayout());

		String url = "gxt/chart/open-flash-chart.swf";

		final Chart chart = new Chart(url);
		chart.setBorders(true);
		chart.setChartModel(getCpuUsed());

		cp.add(chart);

		add(cp, new MarginData(20));
		
		updater = new Timer(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				loadData();
				chart.setChartModel(getCpuUsed());
			}
			
		};
		updater.scheduleRepeating(5000);
	}

	private ChartModel getPieChartData() {
		ChartModel cm = new ChartModel("Sales by Region",
				"font-size: 14px; font-family: Verdana; text-align: center;");
		cm.setBackgroundColour("fffff5");
		Legend lg = new Legend(Position.RIGHT, true);
		lg.setPadding(10);
		cm.setLegend(lg);

		PieChart pie = new PieChart();
		pie.setAlpha(0.5f);
		pie.setNoLabels(true);
		pie.setTooltip("#label# $#val#M<br>#percent#");
		pie.setColours("#ff0000", "#00aa00", "#0000ff", "#ff9900", "#ff00ff");
		pie.addSlices(new PieChart.Slice(100, "AU", "Australia"));
		pie.addSlices(new PieChart.Slice(200, "US", "USA"));
		pie.addSlices(new PieChart.Slice(150, "JP", "Japan"));
		pie.addSlices(new PieChart.Slice(120, "DE", "Germany"));
		pie.addSlices(new PieChart.Slice(60, "UK", "United Kingdom"));
		pie.addChartListener(listener);

		cm.addChartConfig(pie);
		return cm;
	}
	
	private ChartModel getLineChart(){
		ChartModel cm = new ChartModel("Growth per Region", "font-size: 14px; font-family: Verdana;");
		cm.setBackgroundColour("#ffffff");
		XAxis xa = new XAxis();
		xa.setLabels("J", "F", "M", "A", "M", "J", "J", "A", "S", "O",
				"N", "D");
cm.setXAxis(xa);
YAxis ya = new YAxis();
ya.setLabels("0","10","20","30","40","50","60","70", "80", "90","100");
		
		LineChart line = new LineChart();
		line.setAnimateOnShow(true); 
		line.setText("Average");  
		line.setColour("#FF0000");  
		LineDataProvider lineProvider = new LineDataProvider("num"); 
		ListStore<ModelData> store = new ListStore<ModelData>();
		BaseModelData modelData = new BaseModelData();
		modelData.set("num", 5);
		store.add(modelData);
		modelData = new BaseModelData();
		modelData.set("num", 1);
		store.add(modelData);
		modelData = new BaseModelData();
		modelData.set("num", 8);
		store.add(modelData);
		
		lineProvider.bind(store);  
		line.setDataProvider(lineProvider);  
		cm.addChartConfig(line);  
		
		return cm;
	}
	
	
	private static final int SystemInfoPoolMaxSize = 60;
	private List<OperationSystemInfo> SystemInfoPool = new ArrayList<OperationSystemInfo>();
	
	private void loadData(){
		long timestamp = 0;
		if(SystemInfoPool.size() > 0){
			timestamp = SystemInfoPool.get(SystemInfoPool.size()-1).timestamp;
		}
		RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, UrlHelper.toAbsolute("/systemInfo?timestamp=" + timestamp));
		try {
			builder.sendRequest(null, new RequestCallback(){

				@Override
				public void onError(Request arg0, Throwable arg1) {
					// TODO Auto-generated method stub
					displayError("Couldn't retrieve JSON");
				}

				@Override
				public void onResponseReceived(Request request, Response response) {
					// TODO Auto-generated method stub
					if (200 == response.getStatusCode()) {
						JSONValue json = JSONParser.parseStrict(response
								.getText());
						JSONArray array = json.isObject().get("returnObject").isArray();
						for(int i=0; i<array.size(); i++){
							JSONObject obj = array.get(i).isObject();
							if(obj != null){
								OperationSystemInfo info = new OperationSystemInfo();
								JSONString timestamp = obj.get("timestamp").isString();
								if(timestamp == null){	//空的jsonObject
									break;
								}
								info.timestamp = Long.parseLong(timestamp.stringValue());
								info.cpuUsedPercent = obj.get("cpuUsedPercent").isNumber().doubleValue();
								info.cpuWaitPercent = obj.get("cpuWaitPercent").isNumber().doubleValue();
								if(SystemInfoPool.size() > SystemInfoPoolMaxSize){
									SystemInfoPool.remove(0);
								}
								SystemInfoPool.add(info);
							}	
						}
						
					}  else {
						displayError("Couldn't retrieve JSON ("
								+ response.getStatusText() + ")");
					}
				}
				
			});
		} catch (RequestException e) {
			// TODO Auto-generated catch block
			displayError("Couldn't retrieve JSON");
		}
	}
	
	private ChartModel getCpuUsed() {
		int MaxCount = 60;
		ChartModel cm = new ChartModel("Growth per Region",
				"font-size: 14px; font-family: Verdana;");
		cm.setBackgroundColour("#ffffff");
		XAxis xa = new XAxis();
		xa.setLabels("");
		cm.setXAxis(xa);
		final AreaChart cpuUsed = new AreaChart();
		final AreaChart cpuWait = new AreaChart();
		cpuUsed.setFillAlpha(0.3f);
		cpuUsed.setColour("#ff0000");
		cpuUsed.setFillColour("#ff0000");
		cpuWait.setFillAlpha(0.3f);  
		cpuWait.setColour("#00aa00");  
		cpuWait.setFillColour("#00aa00");
		cpuUsed.setTooltip("%#val#");
		cpuWait.setTooltip("%#val#");
		
		double maxValue = 0;
		List<Double> cpuUsedValues = new ArrayList<Double>();
		List<Double> cpuWaitValues = new ArrayList<Double>();
		for(int i=SystemInfoPool.size()-1; i>=0; i--){
			OperationSystemInfo info = SystemInfoPool.get(i);
			double cpuUsedValue = info.getCpuUsedPercent();
			double cpuWaitValue = info.cpuWaitPercent;
			cpuUsedValues.add(cpuUsedValue * 100);
			cpuWaitValues.add(cpuWaitValue * 100);
			
			maxValue = Math.max(Math.max(cpuUsedValue, cpuWaitValue), maxValue);
			//超过表格限制
			if(cpuUsedValues.size() == MaxCount){
				break;
			}
		}
		maxValue = maxValue*100;
		YAxis ya = new YAxis();
		int step = maxValue < 10 ? 1 : maxValue < 50 ? 5 : 10;
		ya.setSteps(step);  
		ya.setMax(step * 10);  
		cm.setYAxis(ya);
		
		cpuUsed.addValues(cpuUsedValues.toArray(new Double[cpuUsedValues.size()]));
		cpuWait.addValues(cpuWaitValues.toArray(new Double[cpuWaitValues.size()]));
		
		while(cpuUsed.getValues().size() < MaxCount){
			cpuUsed.addValues(0);
			cpuWait.addValues(0);
		}
		cm.addChartConfig(cpuUsed);
		cm.addChartConfig(cpuWait);
		return cm;
	}
	
	private void displayError(String message){
		MessageBox.alert("出错", message, null);
	}
	
	
	public static class OperationSystemInfo{
		private long timestamp;		//时间截
		private long totalPhysicalMemorySize;	//总的物理内存
		private long freePhysicalMemorySize;		//剩余的物理内存
		private long totalSwapSpaceSize;			// 交换区总量
		private long freeSwapSpaceSize;			//交换区使用量
		
		private double cpuUsedPercent;			//cpu使用率
		private double cpuWaitPercent;
		private long netSpeed;
		
		public long getTimestamp() {
			return timestamp;
		}

		public long getTotalPhysicalMemorySize() {
			return totalPhysicalMemorySize;
		}

		public long getFreePhysicalMemorySize() {
			return freePhysicalMemorySize;
		}

		public long getTotalSwapSpaceSize() {
			return totalSwapSpaceSize;
		}

		public long getFreeSwapSpaceSize() {
			return freeSwapSpaceSize;
		}

		public double getCpuUsedPercent() {
			return cpuUsedPercent;
		}

		public long getNetSpeed() {
			return netSpeed;
		}
	}

}
